﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Data;
using Com.CodePlex.SPC3.SPbAM.Model;
using Com.CodePlex.SPC3.SPbAM.Properties;
using System.Windows.Input;
using System.IO;
using Microsoft.Win32;
using Com.CodePlex.SPC3.SPbAM.Service;
using Com.CodePlex.SPC3.SPbAM.Controller;
using Com.CodePlex.SPC3.SPbAM.Data;
//using Com.CodePlex.SPC3.SPbAM.View; //should not reference this http://social.msdn.microsoft.com/Forums/is/wpf/thread/3bced3ea-4a97-4456-bfe5-828289bcf971

namespace Com.CodePlex.SPC3.SPbAM.ViewModel {

	public class MainWindowViewModel : ViewModel {

		#region Class
		public static readonly string APPLICATION_NAME = "Com.CodePlex.SPC3.SPbAM";
		private static readonly FileDialogService filedialogservice = new FileDialogService(); //todo: IoC
		#endregion

		//todo: bind cursor using mvvm
		//http://social.msdn.microsoft.com/Forums/en/wpf/thread/ac88f268-25f3-4ddd-b298-b9cd35bee978

		#region Init
		public MainWindowViewModel() {
			DisplayName = MainWindowViewModel.APPLICATION_NAME;
			Mediator.Register(this);
			//note: lazy load: dont do more stuff here
		}
		#endregion

		#region Commands

		private ICommand newcommand;
		public ICommand NewCommand { get { return newcommand ?? (newcommand = new RelayCommand(param => New())); } }

		private ICommand opencommand;
		public ICommand OpenCommand { get { return opencommand ?? (opencommand = new RelayCommand(param => OpenFile(), param => !IsOpening)); } }

		private bool isopening;
		public bool IsOpening {
			get { return isopening; }
			private set {
				if (isopening != value) {
					isopening = value;
					OnPropertyChanged(() => IsOpening);
				}
			}
		}

		private ICommand savecommand;
		public ICommand SaveCommand { get { return savecommand ?? (savecommand = new RelayCommand(param => Save(), param => !IsSaving && (ActiveServerWorkspaceViewModel != null && ActiveServerWorkspaceViewModel.IsModified))); } }

		private ICommand saveascommand;
		public ICommand SaveAsCommand { get { return saveascommand ?? (saveascommand = new RelayCommand(param => SaveAs(), param => !IsSaving && (ActiveServerWorkspaceViewModel != null && ActiveServerWorkspaceViewModel != null))); } }

		private ICommand saveallcommand;
		public ICommand SaveAllCommand { get { return saveallcommand ?? (saveallcommand = new RelayCommand(param => SaveAll(), param => CanSaveAll())); } }

		private bool issaving;
		public bool IsSaving {
			get { return issaving; }
			private set {
				if (issaving != value) {
					issaving = value;
					OnPropertyChanged(() => IsSaving);
				}
			}
		}

		private ICommand closecommand;
		public ICommand CloseCommand { get { return closecommand ?? (closecommand = new RelayCommand(param => OnRequestClose(), param => ActiveServerWorkspaceViewModel != null)); } }

		private ICommand exitcommand;
		public ICommand ExitCommand { get { return exitcommand ?? (exitcommand = new RelayCommand(param => OnRequestExit())); } }

		#endregion

		#region Display Properties

		private string statusbartext;
		public string StatusBarText {
			get { return statusbartext; }
			private set {
				if (statusbartext != value) {
					statusbartext = value;
					OnPropertyChanged(() => StatusBarText);
				}
			}
		}

		private bool isprogressbarvisible;
		public bool IsProgressBarVisible {
			get { return isprogressbarvisible; }
			private set {
				if (isprogressbarvisible != value) {
					isprogressbarvisible = value;
					OnPropertyChanged(() => IsProgressBarVisible);
				}
			}
		}

		private int progress;
		public int Progress {
			get { return progress; }
			private set {
				if (progress != value) {
					progress = value;
					OnPropertyChanged(() => Progress);
				}
			}
		}

		private int activeserverworkspace = 0;
		public int ActiveServerWorkspace {
			get { return activeserverworkspace; }
			set {
				activeserverworkspace = value;
				OnPropertyChanged(() => ActiveServerWorkspace);
			}
		}

		#endregion

		#region Server Workspaces

		//dont bind to the model, as views are destroyed on tab change
		//private ObservableCollection<ServerWorkspaceViewModel> serverworkspaces; 

		//note: kind of bad, because dependancy on View
		private ObservableCollection<View.ServerWorkspaceView> serverworkspaceviews;
		public ObservableCollection<View.ServerWorkspaceView> ServerWorkspaceViews {
			get {
				if (serverworkspaceviews == null) {
					serverworkspaceviews = new ObservableCollection<View.ServerWorkspaceView>();
					serverworkspaceviews.CollectionChanged += (s, e) => {
						if (e.NewItems != null && e.NewItems.Count != 0) {
							foreach (View.ServerWorkspaceView serverworkspace in e.NewItems) {
								((ServerWorkspaceViewModel)serverworkspace.DataContext).PropertyChanged += serverworkspace_PropertyChanged;
								//serverworkspace.RequestClose += serverworkspace_RequestClose;
							}
						}
						if (e.OldItems != null && e.OldItems.Count != 0) {
							foreach (View.ServerWorkspaceView serverworkspace in e.OldItems) {
								((ServerWorkspaceViewModel)serverworkspace.DataContext).PropertyChanged -= serverworkspace_PropertyChanged;
								//serverworkspace.RequestClose -= serverworkspace_RequestClose;
							}
						}
					};
				}
				return serverworkspaceviews;
			}
		}

		private void serverworkspace_PropertyChanged(object sender, PropertyChangedEventArgs e) {
			if (e.PropertyName == "IsModified") {
				this.OnPropertyChanged("SomethingIsModified");
			}
		}

		/*
		public bool SomethingIsModified {
			get {
				return this.AllCustomers.Sum(custVM => custVM.IsSelected ? custVM.TotalSales : 0.0);
			}
		}
		 * */

		/*
		private void serverworkspace_RequestClose(object sender, EventArgs e) {
			ServerWorkspaceViewModel serverworkspace = sender as ServerWorkspaceViewModel;
			serverworkspace.Dispose();
			ServerWorkspaces.Remove(serverworkspace);
		}
		 * */

		private void AddServerWorkspace(ServerWorkspaceViewModel serverworkspace) {
			View.ServerWorkspaceView view = new View.ServerWorkspaceView();
			view.DataContext = serverworkspace;
			ServerWorkspaceViews.Add(view);
			SetActiveServerWorkspace(serverworkspace);
		}

		private void SetActiveServerWorkspace(ServerWorkspaceViewModel serverworkspace) {
			//ICollectionView collectionview = CollectionViewSource.GetDefaultView(ServerWorkspaces);
			//collectionview.MoveCurrentTo(serverworkspace);
			ActiveServerWorkspace = ServerWorkspaceViews.IndexOf(ServerWorkspaceViews.FirstOrDefault(i => i.DataContext == serverworkspace));
		}

		private ServerWorkspaceViewModel ActiveServerWorkspaceViewModel {
			get {
				if (ActiveServerWorkspace != -1 && ServerWorkspaceViews.Count != 0) {
					if (ActiveServerWorkspace < ServerWorkspaceViews.Count) {
						return (ServerWorkspaceViewModel)((View.ServerWorkspaceView)ServerWorkspaceViews[ActiveServerWorkspace]).DataContext;
					}
				}
				return null;
			}
		}

		#endregion

		private void New() {
			ServerWorkspaceViewModel serverworkspace = ServerWorkspaceViewModel.GetNew();
			AddServerWorkspace(serverworkspace);
		}

		private void OpenFile() {
            FileDialogResult result = filedialogservice.ShowOpenFileDialog(new FileType[] { new FileType("Workspace files (*.xml)", ".xml") }, null, System.IO.Path.Combine(Environment.CurrentDirectory, Properties.Settings.Default.WorkingDirectory));
			if (result.IsValid) {
				Open(result.FileName);
			}
		}

		public void Open(string filename) {
			if (IsOpening) {
				throw new Exception("Open - In Progress");
			}
			BackgroundWorker openworker = new BackgroundWorker();
			openworker.WorkerReportsProgress = true;
			openworker.DoWork += (s, e) => {
				((ServerWorkspaceViewModel)e.Argument).Load((i) => {
					openworker.ReportProgress(i);
				});
				e.Result = e.Argument;
			};
			openworker.ProgressChanged += (s, e) => {
				Progress = e.ProgressPercentage;
				//OnProgress();
			};
			openworker.RunWorkerCompleted += (s, e) => {
				if (e.Error != null) {
					//OnOpenedError();	
				} else {
					IsOpening = false;
					StatusBarText = "Ready";
					Progress = 100;
					IsProgressBarVisible = false;
					//OnOpened();
				}
				((ServerWorkspaceViewModel)e.Result).DataBind();
				CommandManager.InvalidateRequerySuggested();
			};
			IsOpening = true;
			StatusBarText = "Opening";
			Progress = 0;
			IsProgressBarVisible = true;
			OnOpening(filename);
			ServerWorkspaceViewModel model = ServerWorkspaceViewModel.GetOpening(filename);
			AddServerWorkspace(model);
			openworker.RunWorkerAsync(model);
		}

		public event EventHandler Opening;

		private void OnOpening(string filename) {
			if (Opening != null) {
				Opening(this, new SimpleEventArgs() { StringValue = filename });
			}
		}

		private void Save() {
			ActiveServerWorkspaceViewModel.SaveCommand.Execute(null);
		}

		private void SaveAs() {
			//ActiveServerWorkspaceViewModel.SaveCommand.Execute(null);
		}

		private bool CanSaveAll() {
			if(IsSaving) {
				return false;
			}
			if (serverworkspaceviews.Count == 0) {
				return false;
			}
			foreach(View.ServerWorkspaceView view in serverworkspaceviews) {
				if(((ServerWorkspaceViewModel)view.DataContext).IsModified) {
					return true;
				}
			}
			return false;
		}

		private void SaveAll() {
			IsSaving = true;
			foreach (View.ServerWorkspaceView view in serverworkspaceviews) {
				ActiveServerWorkspaceViewModel.SaveCommand.Execute(null);
			}	
			IsSaving = false;
		}

		public event EventHandler RequestClose;

		private void OnRequestClose() {
			if (RequestClose != null) {
				RequestClose(this, EventArgs.Empty);
			}
		}

		public bool WarnClose() {
			return ActiveServerWorkspaceViewModel != null && ActiveServerWorkspaceViewModel.IsModified;
		}

		public void Close() {
			ServerWorkspaceViews.RemoveAt(ActiveServerWorkspace);
		}

		public event EventHandler RequestExit;

		private void OnRequestExit() {
			if (RequestExit != null) {
				RequestExit(this, EventArgs.Empty);
			}
		}

		public bool WarnExit() {
			foreach (View.ServerWorkspaceView view in serverworkspaceviews) {
				if (((ServerWorkspaceViewModel)view.DataContext).IsModified) {
					return true;
				}
			}
			return false;
		}

		public void Exit() {
			Mediator.Notify<SimpleMessage>(SimpleMessage.Exit, new SimpleMessage { });
		}
	}
}